package android.tusnotas.activities;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import org.apache.http.conn.ssl.SSLSocketFactory;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ExpandableListActivity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.tusnotas.activities.extras.ShowCourseActivityExtras;
import android.tusnotas.beans.Course;
import android.tusnotas.beans.File;
import android.tusnotas.beans.Folder;
import android.tusnotas.connector.MySSLSocketFactory;
import android.tusnotas.core.FoldersAndFilesAnalyser;
import android.tusnotas.model.TusNotasModel;
import android.tusnotas.services.WebCheckerManager;
import android.tusnotas.util.AlertBuilder;
import android.tusnotas.util.Properties;
import android.tusnotas.util.file.DownloadFile;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import android.widget.Toast;


public class ShowFolders extends ExpandableListActivity {

	// External Storage Properties
	boolean available = false;
	boolean writeable = false;

	public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
	public static final int DIALOG_DOWNLOAD_SUCCESS = 100;
	public static final int DIALOG_FILE_INFO = 1000;
	private static final String path = Environment.getExternalStorageDirectory()+"/webcampus";//"/sdcard/webcampus";
	private ProgressDialog mProgressDialog;
	//  private Dialog successDialog;
	private ProgressDialog pd;
	private Thread thread = null;

	private List<Folder> folders;
	private Course course = null;
	private Map<Integer, Integer> foldersMap;
	private WebCheckerManager webCheckerManager = null;
	private TusNotasModel tusNotasModel = null;
	private String downloadingFileName = null;
	//
	private String downloadingFileExtension = null;
	//
	private View tempView = null;
	private String errorMessage = null;
	private Menu menu = null;
	private KillReceiver mKillReceiver;


	public String getDownloadingFileName() {
		return downloadingFileName;
	}

	public String getFullDownloadingFileName() {
		return path+"/"+downloadingFileName;
	}

	public void setDownloadingFileName(String downloadingFileName) {
		this.downloadingFileName = downloadingFileName;
	}

	public String getDownloadingFileExtension() {
		return downloadingFileExtension;
	}

	public void setDownloadingFileExtension(String downloadingFileExtension) {
		this.downloadingFileExtension = downloadingFileExtension;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		mKillReceiver = new KillReceiver();
		IntentFilter intentFilter = new IntentFilter("kill");
		registerReceiver(mKillReceiver,	intentFilter);

		setContentView(R.layout.show_folders);
		setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

		webCheckerManager = new WebCheckerManager(this);
		tusNotasModel = TusNotasModel.getTusNotasModel(getApplicationContext());

		initilizeThread();
		this.thread.start();
	}

	private void initilizeThread(){	
		pd = ProgressDialog.show(this, 
				getResources().getString(R.string.process_dialog_title_loading),
				getResources().getString(R.string.process_dialog_message_loading),
				Boolean.TRUE, Boolean.FALSE);
		this.thread = new Thread( new Runnable() {
			@Override
			public void run() {
				dataLoader(getIntent());
				pd.dismiss();
				h.sendEmptyMessage(0);
			}
		});
	}

	final Handler h = new Handler(){
		public void handleMessage(Message msg) {
			drawList();
		}           
	};

	private void drawList() {
		if(this.errorMessage != null){
			List<String> datos = new ArrayList<String>();
			datos.add(this.errorMessage);
			ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this,
					android.R.layout.simple_list_item_1, datos);
			ListView lstOpciones = (ListView)findViewById(R.id.LstOpciones);
			lstOpciones.setAdapter(adaptador);
		}else
			if(this.folders.isEmpty()){
				List<String> datos = new ArrayList<String>();
				datos.add(getString(R.string.message_no_files));
				ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this,
						android.R.layout.simple_list_item_1, datos);
				ListView lstOpciones = (ListView)findViewById(R.id.LstOpciones);
				lstOpciones.setAdapter(adaptador);
			} else
			{
				SimpleExpandableListAdapter expListAdapter =
					new SimpleExpandableListAdapter(
							this,
							createGroupList(),
							R.layout.instance_item,
							new String[] { "folderName"},
							new int[] { R.id.instance_desc},
							createChildList(),
							R.layout.file_item,
							new String[] {"fileURL","fileExt", "fileName", "fileSize"},
							new int[] {R.id.file_url, R.id.file_ext, R.id.file_desc, R.id.file_size}
					);

				setListAdapter(expListAdapter);
			}

	}

	private List<Map<String,String>> createGroupList() {
		this.foldersMap = new HashMap<Integer, Integer>();
		List<Map<String,String>> result = new ArrayList<Map<String,String>>();
		Integer i=0;
		for(Folder folder : this.folders){
			this.foldersMap.put(folder.getId(), i++);
			Map<String,String> m = new HashMap<String,String>();
			m.put("folderName", folder.getName());
			result.add(m);
		}

		return result;
	}

	private List<List<Map<String,String>>> createChildList() {

		List<List<Map<String,String>>> result = new ArrayList<List<Map<String,String>>>();
		for(Folder folder : this.folders){
			List<Map<String,String>> secList = new ArrayList<Map<String,String>>();
			for(File file : folder.getFiles()){
				Map<String,String> child = new HashMap<String,String>();
				child.put("fileURL", file.getLink());
				child.put("fileExt", file.getExtension());
				child.put("fileName", file.getName());
				child.put("fileSize", file.getSize().toString());
				secList.add(child);
			}
			result.add(secList);
		}
		return result;
	}


	//gets data from db
	private Integer dataLoader(Intent intent){

		Integer courseId = intent.getIntExtra(ShowCourseActivityExtras.COURSE_ID, -1);
		intent.removeExtra(ShowCourseActivityExtras.COURSE_ID);
		if (courseId == -1) {
			return courseId;
		}
		this.course = tusNotasModel.selectCoursesById(courseId);

		FoldersAndFilesAnalyser foldersAndFilesAnalyser = new FoldersAndFilesAnalyser();
		try {
			this.folders = foldersAndFilesAnalyser.doGetFoldersAndFiles(course.getIdAula());
		} catch (Exception e) {
			this.errorMessage = getString(R.string.message_error_files);
		}
		return 1;
	}

	public void showFileInfo(View view){
		tempView = view;

		TextView tv = null;
		tv = (TextView) ((View) tempView.getParent()).findViewById(R.id.file_size);
		String fileSize = tv.getText().toString();
		tv = (TextView) ((View) tempView.getParent()).findViewById(R.id.file_ext);
		String extension = tv.getText().toString();
		tv = (TextView) ((View) tempView.getParent()).findViewById(R.id.file_desc);
		String fileName = tv.getText().toString();

		AlertDialog.Builder builder2 = new AlertDialog.Builder(this);
		builder2.setTitle(R.string.label_file_info);
		String content = getResources().getString(R.string.label_name) +" "+fileName+"\n"+
		getResources().getString(R.string.label_extension)+" "+extension+"\n"+
		getResources().getString(R.string.label_size)+" "+Integer.parseInt(fileSize)/1024+" Kb";
		builder2.setMessage(content)
		.setCancelable(false)
		.setNegativeButton(getResources().getString(R.string.button_back), 
				new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int id) {
				dialog.cancel();
			}
		})
		.setPositiveButton(R.string.button_download, new MyDownloadFileListener(tempView));
		AlertDialog alert2 = builder2.create();

		alert2.show();		
	}

	public void downloadFile(View view){
		checkExternalStorageState();
		TextView tv = null;
		tv = (TextView) ((View) view.getParent()).findViewById(R.id.file_url);
		String fileURL = tv.getText().toString();
		fileURL = DownloadFile.encodeUrl(fileURL);
		tv = (TextView) ((View) view.getParent()).findViewById(R.id.file_ext);
		String extension = tv.getText().toString();
		tv = (TextView) ((View) view.getParent()).findViewById(R.id.file_desc);
		String fileName = tv.getText().toString();

		if (this.writeable){
			/*Intento de bajar un archivo*/
			String dirdest = path;
			/*Creo el directorio si no existe*/
			DownloadFile.createSavingPath(dirdest);
			/*escribo elnombre del archivo en una variable de instancia para que se
			 * pueda referenciar el nombre del mismo desde un listener*/
			setDownloadingFileName(fileName + extension);
			setDownloadingFileExtension(extension);
			new DownloadFileAsync().execute(fileURL,fileName + extension, dirdest);
		} else {
			// no es posible acceder a la memoria externa
			Toast t = Toast.makeText(getApplicationContext(),R.string.toast_no_external_memory, Toast.LENGTH_SHORT);
			t.setGravity(Gravity.CENTER, 0, 0);
			t.show();
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_DOWNLOAD_PROGRESS:
			mProgressDialog = new ProgressDialog(this);
			mProgressDialog.setMessage("Downloading...");//+R.string.process_dialog_downloading_file);
			mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			mProgressDialog.setCancelable(false);
			mProgressDialog.show();
			return mProgressDialog;
		case DIALOG_DOWNLOAD_SUCCESS:
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setTitle(getResources().getString(R.string.alert_title_downloaded));
			builder.setMessage(getResources().getString(R.string.alert_message_downloaded)+" "+getFullDownloadingFileName())
			.setCancelable(true)
			.setNegativeButton(getResources().getString(R.string.button_back), 
					new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int id) {
					dialog.cancel();
				}
			})
			.setPositiveButton(getResources().getString(R.string.button_open), 
					new MyClickListener());
			AlertDialog alert = builder.create();
			return alert;

		default:
			return null;
		}
	}


	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.configuration:
			Intent welcomeIntent = new Intent(this, Login.class);
			startActivity(welcomeIntent);
			return Boolean.TRUE;

		case R.id.refresh:
			// refresh(Boolean.TRUE);
			Toast t2 = Toast.makeText(getApplicationContext(),R.string.toast_refresh, Toast.LENGTH_SHORT);
			t2.setGravity(Gravity.CENTER, 0, 0);
			t2.show();
			return Boolean.TRUE;

		case R.id.about:
			AlertBuilder.showAboutInfo(this);
			return Boolean.TRUE;

		case R.id.logout:
			
			// delete old hash
			TusNotasModel.getTusNotasModel(getApplicationContext()).updateProperty(Properties.HASH, "");
			Log.e(getClass().getName(),"Deleted saved hash");
			
			AlertBuilder.logout(this);
			return Boolean.TRUE;

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu myMenu) {
		menu = myMenu;
		menu.clear();
		MenuInflater inflater = getMenuInflater();
		if (webCheckerManager.isWebCheckerStarted()) {
			inflater.inflate(R.menu.menu_instances_started, menu);
		} else {
			inflater.inflate(R.menu.menu_instances_stopped, menu);
		}
		return Boolean.TRUE;
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		unregisterReceiver(mKillReceiver);
	}

	private final class KillReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			finish();
		}
	}

	private class MyClickListener implements OnClickListener {

		@Override
		public void onClick(DialogInterface dialog, int which) {
			String fileName = getDownloadingFileName();
			String fileExt = getDownloadingFileExtension();
			java.io.File file = new java.io.File(path + "/" + fileName );
			//java.io.File file = new java.io.File(fileName);
			openFile(file,fileExt);
		}

		private void openFile(java.io.File aFile, String fileExtension) {
			// old version
			Intent myIntent = new Intent();
			Uri uri = Uri.parse("file://"+aFile.getAbsolutePath());
			myIntent.setData(uri);
			myIntent.setAction(Intent.ACTION_VIEW);
			myIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
			try {
				startActivity(myIntent);
			} catch (Exception e) {
				e.printStackTrace();
				try {
					uri = Uri.parse(path+"/");
					myIntent.setData(uri);
					myIntent.setAction(Intent.ACTION_GET_CONTENT);
					// get file extension
					String extension = MimeTypeMap.getFileExtensionFromUrl(fileExtension);
					// get mime type
					String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
					// set the type
					myIntent.setType(mimeType);
					startActivity(myIntent);
				} catch (Exception e1){
					e1.printStackTrace();
					Toast t = Toast.makeText(getApplicationContext(),R.string.toast_cant_open_file, Toast.LENGTH_SHORT);
					t.setGravity(Gravity.CENTER, 0, 0);
					t.show();
				}
			}
		}	 
	}

	private class MyDownloadFileListener implements OnClickListener {

		private View view;

		public MyDownloadFileListener(View view){
			this.view = view;
		}

		@Override
		public void onClick(DialogInterface dialog, int which) {
			downloadFile(this.view);
		}
	}

	class DownloadFileAsync extends AsyncTask<String, String, String> {

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
			showDialog(DIALOG_DOWNLOAD_PROGRESS);
		}

		@Override
		protected String doInBackground(String... arg) {
			int count;

			try {

				URL url = new URL(arg[0]);
				String fileName = arg[1];
				String savingPath = arg[2];

				java.io.File fileOutput = new java.io.File(savingPath + "/" + fileName);

				KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
				trustStore.load(null, null);
				SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
				HttpsURLConnection.setDefaultSSLSocketFactory(((MySSLSocketFactory)sf).getSslContext().getSocketFactory());

				URLConnection conexion = url.openConnection();
				conexion.connect();

				int lenghtOfFile = conexion.getContentLength();
				Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);

				InputStream input = new BufferedInputStream(url.openStream());
				OutputStream output = new FileOutputStream(fileOutput);

				byte data[] = new byte[1024];

				long total = 0;

				while ((count = input.read(data)) != -1) {
					total += count;
					publishProgress(""+(int)((total*100)/lenghtOfFile));
					output.write(data, 0, count);
				}

				output.flush();
				output.close();
				input.close();

			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;

		}
		protected void onProgressUpdate(String... progress) {
			Log.d("ANDRO_ASYNC",progress[0]);
			mProgressDialog.setProgress(Integer.parseInt(progress[0]));
		}

		@Override
		protected void onPostExecute(String unused) {
			removeDialog(DIALOG_DOWNLOAD_SUCCESS);
			dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
			//				mProgressDialog.dismiss();
			//				successDialog.show();
			showDialog(DIALOG_DOWNLOAD_SUCCESS);
		}
	}

	// check the state of the external memory
	private void checkExternalStorageState(){
		String state = Environment.getExternalStorageState();
		if (Environment.MEDIA_MOUNTED.equals(state))
			available = writeable = true;
		else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)){
			available = true;
			writeable = false;
		} else {
			available = writeable = false;
		}
	}

}
